package hust.rpc.client;

import hust.rpc.client.loadbalance.LoadBalance;
import hust.rpc.client.loadbalance.PollingLoadBalance;
import hust.rpc.client.loadbalance.RandomLoadBalance;
import hust.rpc.common.Address;
import hust.rpc.procotol.JsonRpcRequest;
import hust.rpc.util.JsonUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ClientProxy {

    private  static  final Logger logger = LogManager.getLogger();

    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    private static NettyClient client = NettyClient.getInstance();

    private static int count = 0;

//    private static LoadBalance loadBalance = new PollingLoadBalance();
    private static LoadBalance loadBalance = new RandomLoadBalance();


    /**
     * 返回动态代理类
     * @param serviceClass
     * @return
     */
    public static Object getBean(final Class<?> serviceClass){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class<?>[]{serviceClass},(proxy, method, args) -> {
            logger.info("第" + ++count + "次动态代理调用");

            JsonRpcRequest request = new JsonRpcRequest.Builder()
                    .withId(UUID.randomUUID().toString())
                    .withMethod(serviceClass.getName()+"."+method.getName())
//                    .withParams(args[0]+"#"+JsonUtil.ObjectToString(args[1]))
                    .withParams(JsonUtil.ObjectToString(args[0]))
                    .build();

            String name = serviceClass.getName();
            Address address = loadBalance.getAddress(name);

            CompletableFuture<String> future = (CompletableFuture<String>) client.send(new InetSocketAddress(address.getHost(),address.getPort()), request);

            String s = future.get();
            Class<?> returnType = method.getReturnType();
            return JsonUtil.readObjectFromString(s,returnType);
        });
    }


}
